import path from 'path'
import fs from 'fs'
import { execSync } from 'child_process'
import ora from 'ora'
import { NodeSSH } from 'node-ssh'
import AdmZip from 'adm-zip'
import dayjs from 'dayjs'
import { successLog, errorLog, underlineLog } from '../utils/logs'
import { CONFIG } from '../utils/format'

const projectDir = process.cwd()

const ssh = new NodeSSH() // 生成ssh实例

// 部署流程入口
const spinner = ora()
async function deploy (config: CONFIG) {
  const { script, webDir, distPath, projectName, name } = config
  try {
    await execBuild(script)
    await startZip(distPath)
    await connectSSH(config)
    await handleSourceFile(webDir)
    await uploadFile(webDir)
    await unzipFile(webDir)
    await deleteLocalZip()
    successLog(`\n 恭喜您，${underlineLog(projectName)}项目在${underlineLog(name)}上部署成功了^_^\n`)
  } catch (err) {
    errorLog(`部署失败 ${err}`)
  }
  process.exit()
}

// 第一步，执行打包脚本
function execBuild (script: string) {
  return new Promise<void>((resolve, reject) => {
    spinner.text = '开始构建'
    spinner.start()
    execSync(script, { cwd: projectDir, stdio: 'inherit' })
    spinner.succeed(`${script}打包成功`)
    resolve()
  })
}

// 第二步，将脚本打包成zip
function startZip (distPath: string) {
  return new Promise<void>((resolve, reject) => {
    distPath = path.resolve(projectDir, distPath)
    spinner.text = '打包成zip'
    spinner.start()

    const zip = new AdmZip()

    zip.addLocalFolder(distPath)
    zip.writeZip(`${projectDir}/zoro/dist.zip`)
    spinner.succeed('zip打包成功')
    resolve()
  })
}

// 第三步，连接SSH
async function connectSSH (config: CONFIG) {
  const { host } = config
  // const sshConfig = {
  //   host,
  //   port,
  //   username,
  //   password,
  //   privateKeyPath,
  //   passphrase
  // }
  try {
    spinner.text = `连接${underlineLog(host)}`
    spinner.start()
    await ssh.connect(config)
    spinner.succeed(`连接${underlineLog(host)}成功`)
  } catch (err) {
    spinner.warn(`连接${underlineLog(host)}失败: ${err}`)
  }
}

// 第四步，备份远端代码
async function handleSourceFile (webDir: string) {
  spinner.text = '远端备份'
  spinner.start()
  await runCommand(
    `
    if [ -d ${webDir} ];
    then mv ${webDir} ${webDir}_${dayjs().format('YYYY-MM-DD_HH:mm:ss')}
    fi
    `,
    webDir)
  spinner.succeed('远端备份成功')
}

// 第五步，上传zip包
async function uploadFile (webDir: string) {
  try {
    spinner.text = `上传zip至目录${underlineLog(webDir)}`
    spinner.start()
    await ssh.putFile(`${projectDir}/zoro/dist.zip`, `${webDir}/dist.zip`)
    spinner.succeed(`上传zip至目录${underlineLog(webDir)}成功`)
  } catch (err) {
    spinner.warn(`上传zip至目录${underlineLog(webDir)}失败: ${err}`)
  }
}

// 运行命令
async function runCommand (command: string, webDir: string) {
  await ssh.execCommand(command, { cwd: webDir })
}

// 第六步，解压zip包
async function unzipFile (webDir: string) {
  try {
    spinner.text = '开始解压zip包'
    spinner.start()
    await runCommand(`cd ${webDir}`, webDir)
    await runCommand('unzip -o dist.zip && rm -f dist.zip', webDir)
    spinner.succeed('zip包解压成功')
  } catch (err) {
    spinner.warn(`zip包解压失败: ${err}`)
  }
}

// 第七步，删除本地dist.zip包
async function deleteLocalZip () {
  return new Promise<void>((resolve, reject) => {
    spinner.text = '开始删除本地zip包'
    spinner.start()
    fs.unlink(`${projectDir}/zoro/dist.zip`, err => {
      if (err) {
        spinner.warn(`本地zip包删除失败: ${err}`)
        reject(err)
      }
      spinner.succeed('本地zip包删除成功')
      resolve()
    })
  })
}

export default deploy
